package com.example.security.filter;

import com.alibaba.fastjson.JSON;
import com.example.common.enums.CommonMessage;
import com.example.common.util.RedisUtil;
import com.example.common.system.entity.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author chenjf
 * @Date 2022/9/20
 * @Description 前后端分离自定义jwt登录
 */
@Component
@Slf4j
public class JwtLoginFilter extends OncePerRequestFilter {

    @Value("${jwt.token.prefix}")
    private String token;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 遇到的问题：springsecurity放行请求无效
     * 解决办法：查看是否正确返回 filterChain.doFilter(request, response); 如果没有则访问无效,一定要将filterChain.doFilter(request, response);返回
     *
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        LoginUser loginUser = getAuthorization(request);
        if (loginUser != null  && SecurityContextHolder.getContext().getAuthentication() == null)
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        filterChain.doFilter(request, response);
    }


    public LoginUser getAuthorization(HttpServletRequest request){
        String header = request.getHeader(token);
        if (header != null) {
            return getLoginUser(header);
        }
        return null;
    }

    public LoginUser getLoginUser(String header){
        String json = redisUtil.get(CommonMessage.REDIS_TOKEN.getValue() + header);

        if (null == json) {
            return null;
        }
        LoginUser loginUser = JSON.parseObject(json, LoginUser.class);
        //刷新缓存时间
        redisUtil.expire(CommonMessage.REDIS_TOKEN.getValue() + header, 30, TimeUnit.MINUTES);
        return loginUser;
    }
}
/*

@Override
	public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		//只处理http请求
		if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
			throw new ServletException("OncePerRequestFilter just supports HTTP requests");
		}
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;

		//判断这个请求是否需要执行过滤
		String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
		boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;

		if (hasAlreadyFilteredAttribute || skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) {

			// 直接放行，不执行此过滤器的过滤操作
			filterChain.doFilter(request, response);
		} else {
			// 执行过滤，并且向请求域设置一个值，key就是生成的全局唯一的·alreadyFilteredAttributeName·
			request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
			try {
				//由子类自己去实现拦截的逻辑  注意 自己写时，filterChain.doFilter(request, response);这句代码不要忘了
				doFilterInternal(httpRequest, httpResponse, filterChain);
			}
			finally {
				// Remove the "already filtered" request attribute for this request.
				request.removeAttribute(alreadyFilteredAttributeName);
			}
		}
	}
 */